﻿using System;
using System.Collections.Generic;
using FireStarterModeller.BO;
using FireStarterModeller.Test.BO;
using FireStarterModeller.UI;
using Habanero.Base;
using Habanero.Faces.Base;
using NUnit.Framework;
using Rhino.Mocks;

namespace FireStarterModeller.Test.UI
{
    [TestFixture]
    public class TestSolutionValidator
    {
        [TestFixtureSetUp]
        public void SetupFixture()
        {
            UITestUtils.SetupFixture();
        }


        [SetUp]
        public virtual void SetupTest()
        {
            UITestUtils.SetupTest();
        }

        private static DMSolution CreateDMSolution()
        {
            DMSolution dmSolution = new DMSolution();
            dmSolution.SolutionName = TestUtilsShared.GetRandomString();
            return dmSolution;
        }


        [Test]
        public void Test_Construct_WhenControlFactoryNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                new SolutionValidator(null, formsController);
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("solution", ex.ParamName);
            }
        }

        [Test]
        public void Test_Construct_WhenFormsControllerNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                new SolutionValidator(dmSolution,null);
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("formsController", ex.ParamName);
            }
        }

        [Test]
        public void Test_ValidateSolution_ShouldReturnBOErrorsCountGreaterThanZero_WhenSolutionNotValid()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsDMSolution.CreateSavedDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IBOError> boErrors = solutionValidator.ValidateSolution();
            //---------------Test Result -----------------------
            Assert.Greater(boErrors.Count, 0);
        }

        [Test]
        public void Test_ValidateSolution_ShouldReturnBOErrorsCount0_WhenSolutionValid()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsDMSolution.CreateSavedDMSolution(); //CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IBOError> boErrors = solutionValidator.ValidateSolution();
            //---------------Test Result -----------------------
            Assert.AreEqual(0, boErrors.Count);
        }

        [Test]
        public void Test_HasErrors_ShouldReturnFalse_WhenSolutionValid()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = TestUtilsDMSolution.CreateSavedDMSolution(); //CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IBOError> errors;
            bool hasErrors = solutionValidator.HasErrors(out errors);
            //---------------Test Result -----------------------
            Assert.IsFalse(hasErrors);
        }

        [Test]
        public void Test_HasErrors_ShouldReturnTrue_WhenSolutionNotValid()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IBOError> errors;
            bool hasErrors = solutionValidator.HasErrors(out errors);
            //---------------Test Result -----------------------
            Assert.IsTrue(hasErrors);
        }

        [Test]
        public void Test_HasWarningsOnly_ShouldReturnTrue_WhenOnlyWarnings()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            IList<IBOError> errors;
            bool hasErrors = solutionValidator.HasErrors(out errors);
            errors = RemoveAllForErrorLevel(errors,ErrorLevel.Error);
            //---------------Assert Precondition----------------
            Assert.IsTrue(hasErrors);
            Assert.Greater(errors.Count,0);
            //---------------Execute Test ----------------------
            bool hasWarningsOnly = SolutionValidator.HasWarningsOnly(errors);
            //---------------Test Result -----------------------
            Assert.IsTrue(hasWarningsOnly);
        }

        [Test]
        public void Test_HasWarningsOnly_ShouldReturnFalse_WhenErrorsAndWarnings()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            IList<IBOError> errors;
            bool hasErrors = solutionValidator.HasErrors(out errors);
            //---------------Assert Precondition----------------
            Assert.IsTrue(hasErrors);
            Assert.Greater(errors.Count, 0);
            //---------------Execute Test ----------------------
            bool hasWarningsOnly = SolutionValidator.HasWarningsOnly(errors);
            //---------------Test Result -----------------------
            Assert.IsFalse(hasWarningsOnly);
        }

        [Test]
        public void Test_HasErrorsOnly_ShouldReturnTrue_WhenOnlyErrors()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            IList<IBOError> errors;
            bool hasErrors = solutionValidator.HasErrors(out errors);
            errors = RemoveAllForErrorLevel(errors,ErrorLevel.Warning);
            //---------------Assert Precondition----------------
            Assert.IsTrue(hasErrors);
            Assert.Greater(errors.Count,0);
            //---------------Execute Test ----------------------
            bool hasErrorsOnly = SolutionValidator.HasErrorsOnly(errors);
            //---------------Test Result -----------------------
            Assert.IsTrue(hasErrorsOnly);
        }

        [Test]
        public void Test_HasErrorsOnly_ShouldReturnFalse_WhenErrorsAndWarnings()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            IList<IBOError> errors;
            bool hasErrors = solutionValidator.HasErrors(out errors);
            //---------------Assert Precondition----------------
            Assert.IsTrue(hasErrors);
            Assert.Greater(errors.Count, 0);
            //---------------Execute Test ----------------------
            bool hasErrorsOnly = SolutionValidator.HasErrorsOnly(errors);
            //---------------Test Result -----------------------
            Assert.IsFalse(hasErrorsOnly);
        }


        [Test]
        public void Test_HasErrorsOnlyNoParameter_ShouldUseErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            IList<IBOError> errors = solutionValidator.ValidateSolution();
            //---------------Execute Test ----------------------
            bool hasErrorsOnly = solutionValidator.HasErrorsOnly();
            //---------------Test Result -----------------------
            Assert.AreEqual(SolutionValidator.HasErrorsOnly(errors), hasErrorsOnly);
        }

        [Test]
        public void Test_HasErrorsOnlyNoParameter_ShouldUseSolution()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            //---------------Execute Test ----------------------
            bool hasErrorsOnly = solutionValidator.HasErrorsOnly();
            //---------------Test Result -----------------------
            Assert.IsFalse(hasErrorsOnly);
        }

        [Test]
        public void Test_HasWarningsOnlyNoParameter_ShouldUseErrorList()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            IList<IBOError> errors = solutionValidator.ValidateSolution();
            //---------------Execute Test ----------------------
            bool warningsOnly = solutionValidator.HasWarningsOnly();
            //---------------Test Result -----------------------
            Assert.AreEqual(SolutionValidator.HasWarningsOnly(errors), warningsOnly);
        }

        [Test]
        public void Test_HasWarningsOnlyNoParameter_ShouldUseSolution()
        {
            //---------------Set up test pack-------------------
            DMSolution dmSolution = CreateDMSolution();
            IFireStarterFormsController formsController = MockRepository.GenerateStub<IFireStarterFormsController>();
            SolutionValidator solutionValidator = new SolutionValidator(dmSolution, formsController);
            dmSolution.AllClasses.CreateBusinessObject();
            //---------------Execute Test ----------------------
            bool warningsOnly = solutionValidator.HasWarningsOnly();
            //---------------Test Result -----------------------
            Assert.IsFalse(warningsOnly);
        }

        private IList<IBOError> RemoveAllForErrorLevel(IList<IBOError> errors,ErrorLevel errorLevel)
        {
            IList<IBOError> requiredValues = new List<IBOError>();
            foreach (IBOError boError in errors)
            {
                if (boError.Level != errorLevel)
                    requiredValues.Add(boError);
            }
            return requiredValues;
        }
    }
}
